package com.xlh.aop.statistic;

import com.xlh.common.ResultEnum;
import com.xlh.exception.StatisticLockException;
import com.xlh.lock.KeyLock;
import com.xlh.util.AnnotationResolver;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.TimeUnit;


/**
 * 一个方法只有在获取锁后才能执行
 *
 * @author lx
 */
@Aspect
@Component
public class StatisticAcquireLockAspect {

    @Autowired
    private KeyLock<String> statisticLock;

    @Before("@annotation(StatisticPreAcquireLock)")
    public void requireLock(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        StatisticPreAcquireLock preAcquireLock = method.getAnnotation(StatisticPreAcquireLock.class);

        String key = AnnotationResolver.resolver(joinPoint, preAcquireLock.value());
        int timeout = preAcquireLock.timeout();

        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getResponse();

        if (Objects.equals(preAcquireLock.type(), 2)) {
            if (statisticLock.isLocked(key)) {
                response.addHeader("code-message", String.valueOf(ResultEnum.STATISTIC_LOCK_EXCEPTION.getCode()));
                throw new StatisticLockException();
            }
        } else {
            if (timeout == 0) {
                if (!statisticLock.tryLock(key)) {
                    response.addHeader("code-message", String.valueOf(ResultEnum.STATISTIC_LOCK_EXCEPTION.getCode()));
                    throw new StatisticLockException();
                }
            } else {
                if (!statisticLock.tryLock(key, timeout, TimeUnit.SECONDS)) {
                    response.addHeader("code-message", String.valueOf(ResultEnum.STATISTIC_LOCK_EXCEPTION.getCode()));
                    throw new StatisticLockException();
                }
            }
        }

    }

}
